/*
 *  class IME (Input Method Engine), base class of all InputMethod
 */
function IME() {
  this._context = {
    'input': '',
    'option': '',
    'result': '',
    'currentpage':0
  };
  this.name = 'IME';
  this.officialName = '';
  this.pagesize = 10;
  return this;
}

IME.prototype.resetContext = function () {
  this._context['input'] = '';
  this._context['option'] = '';
  this._context['result'] = '',
  this._context['currentpage'] = 0;
}

IME.prototype.getName = function () {   
  return this.name;
};

IME.prototype.getOfficialName = function () {
  return this.officialName;
};

IME.prototype.getContext = function () {
  return this._context;
};

IME.prototype.processInput = function (s) {
  ;
};

IME.prototype.selectResult = function (s) {
  ;
};

// return an array
IME.prototype.getCurrentOption = function () {
  s = this._context['option'].substr(this._context['currentpage']*this.pagesize*2, this.pagesize*2);
  if (s == '') {
    return [];
  } 
  if (',' == s.charAt(s.length-1)) {
    s = s.substr(0, s.length-1);
  } 
  return s.split(',');   
}

IME.prototype.nextPage = function () {
  total_page = Math.ceil(this._context['option'].length/(this.pagesize*2));
  //console.log(total_page);
  if (this._context['currentpage']+1 < total_page) {
    this._context['currentpage'] += 1;
  }
}

IME.prototype.hasNextPage = function () {
  total_page = Math.ceil(this._context['option'].length/(this.pagesize*2));
  return (this._context['currentpage']+1) < total_page;
}

IME.prototype.previousPage = function () {
  if (this._context['currentpage'] > 0) {
    this._context['currentpage'] -= 1;
  }
}

IME.prototype.hasPreviousPage = function () {
  return this._context['currentpage'] != 0;
}

/*
 *  delete user input. updateContext should be invoked after deleteInput.
 */
IME.prototype.deleteInput = function () {
  //console.log('deleteInput');
  if (this._context['input'].length != 0) {
    this._context['input'] = this._context['input'].substr(0, 
      this._context['input'].length-1);
  }
  this._context['currentpage'] = 0;
}
//  end definition of IME

/*
 *  class StrokeIM
 */
function StrokeIM() {
  this.name = 'StrokeIM';
  this.officialName = '笔画';
  this.keytable = {
    button1: 'a',
    button2: 'b',
    button3: 'c',
    button4: 'd',
    button5: 'e',
    button6: undefined,
    button7: undefined,
    button8: undefined,
    button9: undefined,
    button0: undefined,
    buttonstar: undefined, // reserved
    buttonwell: undefined // reserved
  };
  return this;
}

StrokeIM.prototype = new IME();

/*
 *  eat user input. updateContext should be invoked after processInput.
 */
StrokeIM.prototype.processInput = function (s) {
  // for input
  if (this.keytable[s] != undefined) { 
    this._context['input'] += this.keytable[s];
    this._context['currentpage'] = 0;
  }
}

/*
 *  update StrokeIM context. 
 */
StrokeIM.prototype.updateContext = function () {
  pre_option = this._context['option'];
  this._context['option'] = '';
  if (0 != this._context['input'].length) {
    for (i in stroketable) {
      if (i.indexOf(this._context['input']) == 0) {
        this._context['option'] += stroketable[i]+',';
      }
    }
    
    if (0 == this._context['option'].length) {
      this._context['input'] = this._context['input'].substr(0, 
        this._context['input'].length-1);
      this._context['option'] = pre_option;
    }
  }
}

/*
 *  get input array
 */
StrokeIM.prototype.getInput = function () {
  mapping = {a:'一', b:'丨', c:'丿', d:'丶', e:'乙'};
  input_str = this._context['input'];
  ret = new Array();
  for (i=0; i<input_str.length; i++) {
    ret[i] = mapping[input_str.charAt(i)];
  }
  return ret;
}

/*
 *  1. this function take one result as parameter, return nothing
 *  2. this is used to generate legend word, fulfill result in _context['option']
 *  3. further feature: record user input habit into cookie or server data store. 
 */
StrokeIM.prototype.selectResult = function (s) { 
  legend_str = '';
  for (i=0; i<wordlibrary.length; i++) {
    if (s == wordlibrary[i].charAt(0)) {
      legend_str += wordlibrary[i].charAt(1)+',';
    }
  }
  // logging('legend_str: '+legend_str);
  this._context['option'] = legend_str;
  this._context['input'] = '';
  this._context['currentpage'] = 0;
}
// end definition of StrokeIM

/*
 *  NumberIM
 */
function NumberIM() {
  this.name = 'NumberIM';
  this.officialName = '数字';
  this.keytable = {
    button1: '1',
    button2: '2',
    button3: '3',
    button4: '4',
    button5: '5',
    button6: '6',
    button7: '7',
    button8: '8',
    button9: '9',
    button0: '0',
    buttonstar: undefined,
    buttonwell: undefined
  }
  return this;
}

NumberIM.prototype = new IME();

NumberIM.prototype.processInput = function (s) {
  // for input
  if (this.keytable[s] != undefined) {
    this.resetContext();
    this._context['result'] = this.keytable[s];
  } else {
    this._context['result'] = '';
  }
}

NumberIM.prototype.updateContext = function () {
  ;
}
// end definition of NumberIM

/*
 *  CharIM
 */
function CharIM() {
  this.name = 'CharIM';
  return this
}

CharIM.prototype = new IME();

CharIM.prototype.processInput = function (s) {
  // for input
  if (this.keytable[s] != undefined) {
    this.resetContext();
    this._context['input'] = s.substr(6);
  }
}

CharIM.prototype.updateContext = function () {
  this._context['option'] = '';
  if (this._context['input'] != '') {
    option_str = this.keytable['button'+this._context['input']];
    for (i=0; i<option_str.length; i++) {
      this._context['option'] += option_str.charAt(i) + ',';
    }
  } else {
    this.resetContext();
  }
}

CharIM.prototype.getInput = function () {
  if (this._context['input'] == '') {
    return [];
  } else {
    return [this._context['input']];
  }
}
// end definition of CharIM

/*
 *  UpperCharIM()
 */
function UpperCharIM() {
  this.name = 'UpperCharIM';
  this.officialName = '大写字母';
  this.keytable = {
    button1: undefined,
    button2: 'ABC',
    button3: 'DEF',
    button4: 'GHI',
    button5: 'JKL',
    button6: 'MNO',
    button7: 'PQRS',
    button8: 'TUV',
    button9: 'WXYZ',
    button0: undefined,
    buttonstar: undefined,
    buttonwell: undefined
  };
  return this;
}

UpperCharIM.prototype = new CharIM();
// end definition of UpperCharIM

/*
 *  LowerCharIM
 */ 
function LowerCharIM () {
  this.name = 'LowerCharIM';
  this.officialName = '小写字母';
  this.keytable = {
    button1: undefined,
    button2: 'abc',
    button3: 'def',
    button4: 'ghi',
    button5: 'jkl',
    button6: 'mno',
    button7: 'pqrs',
    button8: 'tuv',
    button9: 'wxyz',
    button0: undefined,
    buttonstar: undefined,
    buttonwell: undefined
  };  
  return this;
}

LowerCharIM.prototype = new CharIM();
// end definition of LowerCharIM

/*
 *  SymbolIM
 */
function SymbolIM() {
  this.name = 'SymbolIM';
  this.officialName = '符号';
}

SymbolIM.prototype = new IME();

SymbolIM.prototype.processInput = function (s) {
  ;
};

SymbolIM.prototype.updateContext = function () {
  this._context['option'] = '。,，,？,！,：,、,“,”,《,》,\',-,（,）,@,/,_,[,],;,+,#,￥,%,$,……,&,*,|';
};

SymbolIM.prototype.getInput = function() {
  return [];
};
// end definition of SymbolIM
